using Gameplay.PVE.Entity;
using Gameplay.PVE.Utils;
using ImageEffects;
using RootMotion.FinalIK;
using System.Collections.Generic;
using AudioStudio;
using Cinemachine;
using DG.Tweening;
using Gameplay.PVE.Skill;
using UnityEngine;
using UnityEngine.Rendering;
using Yoozoo.Libs;

namespace Gameplay.PVE
{
    public class RenderComponent:IComponent,ITransmit
    {
        //渲染

        private UnitBase unit;
        private GameObject renderer;
        private Animator animator;
        private Animator[] animators;
        private string m_action = string.Empty;
        private string m_moveAttackAction = string.Empty;
        private bool needPlayDead = false;
        private string m_currentFrameAction = string.Empty;
        private SkinnedMeshRenderer[] meshRender;
        private bool needShowShadow;//残影
        private List<GhostShadow> shadowList = new List<GhostShadow>();
        private float shadowInterval = 0.03f;
        private float lastShadowTime;
        
        private List<Material> shadowMat = new List<Material>();
        private List<RendererMatData> renderMats = new List<RendererMatData>();

        private Dictionary<int, List<GameObject>> hairs = new Dictionary<int, List<GameObject>>();
        
        //private List<MaterialPropertyBlock> skinnedMeshBlock = new List<MaterialPropertyBlock>();
        private CinemachineVirtualCameraBase bossComeCamera;
        private CinemachineVirtualCameraBase bossFixedCamera;

        private class RendererMatData
        {
            public Renderer renderer;
            public Material[] originMats;
            public Material[] deadMats;
            public MaterialPropertyBlock propertyBlock;
        }
        
        private static readonly int MaskAmount = Shader.PropertyToID("_MaskAmount");
        private static readonly int MaskColor = Shader.PropertyToID("_MaskColor");

        private float flashDuration = 0.1f;
        private float flashFade = 0.1f;
        private float flashStartTime = 0;
        private float lastFlashAmount = 0;

        private float shakeStartTime;
        private float shakeTime;
        private float shakeInterval;
        private float lastShakeTime;
        private float shakeIntensity;
        private Vector3 shakeOffset;


        private AudioSource audioSource;

        private AimIK ikCom;
        private Transform rotationAnchorPoint;
        private Vector3 rotationAnchorPointOriginAngles;

        private GameObject skillModel;
        private Animator skillAnimator;
        private Animator effectAnimator;

        private int attackFullLayerIndex;
        private int attackTopLayerIndex;

        public Material clothMobileUEMat;
        private bool _ShowShadow = true;

        private Vector3 rendererOffset;
        private Transform animRoot;
        private bool isAirDrone = false;

        private bool isShowingIn = false;
        private float showInTime = 0;
        private float showInStartTime = 0;

        private ModelInTimeline timelineMono;

        private Vector3 lookAtTargetForward;
        
        
        private struct GhostShadow
        {
            public GameObject gameObject;
            public List<Material> mats;
            public float fadeTime;
            public float endTime;
        }

        void IClass.OnReset()
        {
            lastAttackState = 0;
            if (rotationAnchorPoint != null)
            {
                rotationAnchorPoint.localEulerAngles = rotationAnchorPointOriginAngles;
            }
            rotationAnchorPoint = null;
            timelineMono = null;
            isShowingIn = false;
            isDropping = false;
            if (animRoot != null)
            {
                animRoot.transform.localPosition = rendererOffset;
            }
            animRoot = null;
            deadTurnDarkStartTime = 0;
            TimeManager.Instance.CancelDelayCall(deadCallId);
            TimeManager.Instance.CancelDelayCall(deadDissolveCallId);
            TimeManager.Instance.CancelDelayCall(deadTurnDarkCallId);
            TimeManager.Instance.CancelDelayCall(deadDisappearCallId);
            TimeManager.Instance.CancelDelayCall(deadHelicopterCallId);
            deadCallId = 0;
            deadDissolveCallId = 0;
            deadTurnDarkCallId = 0;
            deadDisappearCallId = 0;
            deadHelicopterCallId = 0;
            for (int i = 0; i < renderMats.Count; i++)
            {
                if (renderMats[i].deadMats == null || renderMats[i].originMats == null)
                {
                    continue;
                }
                for (int j = 0; j < renderMats[i].deadMats.Length; j++)
                {
                    GameObject.DestroyImmediate(renderMats[i].deadMats[j]);
                }

                if (renderMats[i].renderer != null)
                {
                    renderMats[i].renderer.materials = renderMats[i].originMats;
                }
                for (int j = 0; j < renderMats[i].originMats.Length; j++)
                {
                    renderMats[i].originMats[j].SetFloat("_Darkness",0);
                }
            }
            renderMats.Clear();
            targetBlendValue.Clear();
            currentBlendValue.Clear();
            animator = null;
            if (renderer != null)
            {
                renderer.transform.localScale = unit.Data.rendererOriginScale;
                ResetHairsLayer();
                UpdateAttackState(true);
                PveResourceManager.RecoverResource(renderer,PveResourceManager.EPveResType.Model,unit.Data.modelId);
            }
            ResetTimeline();
            renderer = null;
            if (skillModel != null)
            {
                PveResourceManager.RecoverResource(skillModel,PveResourceManager.EPveResType.Model,unit.Data.skillModelId);
            }

            meshRender = null;
            skillModel = null;
            m_action = string.Empty;
            m_currentFrameAction = string.Empty;
            isShowKnockBack = false;
            needShowShadow = false;
            if (ikCom != null)
            {
                ikCom.solver.target = null;
                ikCom.solver.SetIKPositionWeight(0);
                ikCom.enabled = false;
            }
            ClearShadow();
            hairs.Clear();
            if (unit.Data.modelId == PveGlobalVlues.HelicopterModelId)
            {
                AudioManager.StopSound("sfx_rpg_helicopter_idle",unit.gameObject);
            }
        }

        void IComponent.OnInitialize(UnitBase unit)
        {
            this.unit = unit;
        }
        public void Initialize(UnitBase unit)
        {
            ((IComponent)this).OnInitialize(unit);
        }

        public void Dispose()
        {
            ((IClass)this).OnReset();
        }
        
        
        public void Birth()
        {
            ((IComponent)this).OnBirth();
        }
        
        public void Update()
        {
            ((IComponent) this).OnUpdate();
        }

        void IComponent.OnUpdate()
        {
            if (isShowingIn)
            {
                if (TimeManager.logicTime - showInStartTime > showInTime)
                {
                    unit.Data.isShowingSpawn = false;
                    isShowingIn = false;
                    Play("Idle");
                    if (bossFixedCamera)
                    {
                        PveCameraManager.Instance.ResetBattleFixFakeCamera(bossFixedCamera);
                    }
                }
            }
            SetDirection();
        }

        private int lastAttackState;

        private void UpdateAttackState(bool force = false)
        {
            if (animator == null)
            {
                return;
            }

            if (lastAttackState != unit.Data.attackState || force)
            {
                if (unit.Data.attackState == 0)
                {
                    if (attackFullLayerIndex >= 0)
                    {
                        animator.SetLayerWeight(attackFullLayerIndex,0);
                    }
                    if (attackTopLayerIndex >= 0)
                    {
                        animator.SetLayerWeight(attackTopLayerIndex,0);
                    }
                }
                else if (unit.Data.attackState == 1)
                {
                    if (attackFullLayerIndex >= 0)
                    {
                        animator.SetLayerWeight(attackFullLayerIndex,1);
                    }
                    if (attackTopLayerIndex >= 0)
                    {
                        animator.SetLayerWeight(attackTopLayerIndex,0);
                    }
                }
                else if (unit.Data.attackState == 2)
                {
                    if (attackFullLayerIndex >= 0)
                    {
                        animator.SetLayerWeight(attackFullLayerIndex,0);
                    }
                    if (attackTopLayerIndex >= 0)
                    {
                        animator.SetLayerWeight(attackTopLayerIndex,1);
                    }
                }
                
                lastAttackState = unit.Data.attackState;
            }
        }

        /*private void UpdateLookAtDirection()
        {
            if (lookAtTargetForward == Vector3.zero || rotationAnchorPoint == null)
            {
                return;
            }
            
        }*/
        
        public void OnFixedUpdate()
        {

            if (needShowShadow)
            {
                if (TimeManager.gameTime - lastShadowTime >= shadowInterval)
                {
                    CreateShadow();
                    lastShadowTime = TimeManager.gameTime;
                }
            }

            CheckShadowLifeTime();
            CheckFlash();
            CheckShake();
            CheckBlend();
            CheckDeadDissolve();
            if (isShowKnockBack)
            {
                DoKnockBack();
            }
            CheckAirDroneDead();
            //UpdateAttackState();
        }

        private void UpdateForward()
        {
            if (unit.Data.isDead || renderer == null ||  isShowingIn)
            {
                return;
            }

            if (animator != null && animator.applyRootMotion)
            {
                unit.Data.moveOffset = renderer.transform.position - unit.Data.position;
                renderer.transform.localPosition = Vector3.zero;
                //fixbug 新手引导小黑通过turnright控制旋转失效
                //renderer.transform.localEulerAngles = Vector3.zero;
            }
            else
            {
                unit.Data.moveOffset = Vector3.zero;
                renderer.transform.localPosition = shakeOffset;
            }
            return;
            if (unit.Data.isDead || renderer == null)
            {
                return;
            }

            if (unit.Data.isManualMoving || unit.Data.isApplyAnimationMovement)
            {
                if (unit.Data.IsInSkill() && !unit.Data.isApplyAnimationMovement)
                {
                    unit.Data.moveOffset = Vector3.zero;
                    return;
                }

                unit.Data.moveOffset = renderer.transform.position - unit.Data.position;
                if (unit.Data.moveState == 1)
                {
                    /*var v = targetBlendValue["WalkV"];
                    var h = targetBlendValue["WalkH"];
                    var a = Mathf.Abs(v) + Mathf.Abs(h);
                    var realSpeed = Mathf.Sqrt((v / a / 0.8f) * (v / a / 0.8f) + (h / a) * (h / a));
                    //Debug.LogError(h + " " + v + " " + realSpeed);
                    unit.Data.moveOffset = unit.Data.moveOffset / realSpeed;*/
                }

                //Debug.LogError(unit.Data.moveOffset);
                //unit.Data.moveOffset.y = 0;

                /*unit.Data.moveForwardOffset = renderer.transform.localPosition.normalized;
                unit.Data.moveForwardOffset.y = 0;*/
                renderer.transform.localPosition = Vector3.zero;
                renderer.transform.localEulerAngles = Vector3.zero;
            }

            renderer.transform.localPosition = shakeOffset;
        }

        private void CheckFlash()
        {
            if (flashStartTime != 0)
            {
                
                if (TimeManager.gameTime - flashStartTime > flashDuration)
                {
                    float percent = (TimeManager.gameTime - flashStartTime - flashDuration) / (flashFade);
                    if (percent <= 1)
                    {
                        SetFlashAmount(lastFlashAmount * (1 - percent));
                    }
                    else
                    {
                        flashStartTime = 0;
                        SetFlashAmount(0);
                    }
                }
                /*else if (TimeManager.logicTime - flashStartTime > flashDuration)
                {
                    
                }*/
                /*float percent = (TimeManager.logicTime - flashStartTime) / (flashDuration+flashFade);
                if (percent <= 1)
                {
                    SetFlashAmount(lastFlashAmount * (1 - percent));
                }
                else
                {
                    flashStartTime = 0;
                    SetFlashAmount(0);
                }*/
            }
        }

        private void SetFlashAmount(float amount)
        {
            /*for (int i = 0; i < flashMat.Count; i++)
            {
                flashMat[i].SetFloat(FlashAmount,amount);
            }*/
            for (int i = 0; i < renderMats.Count; i++)
            {
                renderMats[i].propertyBlock.SetFloat(MaskAmount,amount);
                renderMats[i].renderer.SetPropertyBlock(renderMats[i].propertyBlock);
            }
        }

        private void SetFlashColor(Color color)
        {
            /*for (int i = 0; i < flashMat.Count; i++)
            {
                flashMat[i].SetColor(FlashColor,color);
            }*/
            for (int i = 0; i < renderMats.Count; i++)
            {
                renderMats[i].propertyBlock.SetColor(MaskColor,color);
                renderMats[i].renderer.SetPropertyBlock(renderMats[i].propertyBlock);
            }
        }

        public void SetLayer(int layer)
        {
            if (renderer != null)
            {
                renderer.SetLayerRecursively(layer);
            }

            if (skillModel != null)
            {
                skillModel.SetLayerRecursively(layer);
            }
            
            if (layer == PveUtils.pveUnitLayer)
            {
                ResetHairsLayer();
            }
        }

        private void ResetHairsLayer()
        {
            foreach (var item in hairs)
            {
                var list = item.Value;
                for (int i = 0; i < list.Count; i++)
                {
                    list[i].layer = item.Key;
                }
            }
        }

        public GameObject GetModel()
        {
            var model = this.renderer;
            this.renderer = null;
            return model;
        }

        private void CreateShadow(float time = 0f)
        {
            if (meshRender == null)
            {
                return;
            }
            for (int i = 0; i < meshRender.Length; i++)
            {
                if (meshRender[i] == null)
                {
                    return;
                }
                Mesh mesh = new Mesh ();
                meshRender[i].BakeMesh(mesh);

                GameObject go = new GameObject();
                //go.hideFlags = HideFlags.HideAndDontSave;//面板不显示

                MeshFilter filter = go.AddComponent<MeshFilter>();
                filter.mesh = mesh;

                MeshRenderer meshRen = go.AddComponent<MeshRenderer>();

                meshRen.material = PveResourceManager.GetPhantomMat();
                
                //meshRen.material.shader = ghostShader;//设置xray效果
                //meshRen.material.SetFloat("_Intension", Intension);//颜色强度传入shader中*/

                go.transform.localScale = meshRender[i].transform.localScale;
                go.transform.position = meshRender[i].transform.position;
                go.transform.rotation = meshRender[i].transform.rotation;

                
                //item.meshRenderer = meshRen;
                shadowList.Add(new GhostShadow
                {
                    gameObject = go,
                    mats = new List<Material>{meshRen.material},
                    endTime = TimeManager.gameTime + time,
                    fadeTime = 0.2f,
                });
            }
        }

        private void CheckShadowLifeTime()
        {
            for (int i = 0; i < shadowList.Count; i++)
            {
                if (TimeManager.gameTime > shadowList[i].endTime + shadowList[i].fadeTime)
                {
                    GameObject.DestroyImmediate(shadowList[i].gameObject);
                    shadowList.RemoveAt(i);
                    i--;
                }
                else if (TimeManager.gameTime > shadowList[i].endTime)
                {
                    float percent = (TimeManager.gameTime - shadowList[i].endTime) / shadowList[i].fadeTime;
                    for (int j = 0; j < shadowList[i].mats.Count; j++)
                    {
                        var color = shadowList[i].mats[j].GetColor("_RimColor");
                        float alpha = 1 - percent;
                        percent = 0;
                        var newColor = new Color(Mathf.Lerp(color.r,1,percent), Mathf.Lerp(color.g,1,percent), Mathf.Lerp(color.b,1,percent),alpha);
                        shadowList[i].mats[j].SetColor("_RimColor",newColor);
                    }
                }
            }
        }

        private void ClearShadow()
        {
            for (int i = 0; i < shadowList.Count; i++)
            {
                GameObject.DestroyImmediate(shadowList[i].gameObject);
            }
            shadowList.Clear();
        }
        
        
        void IComponent.OnBirth()
        {
            lastAttackState = 0;
            needShowShadow = false;
            lookAtTargetForward = Vector3.zero;
          
            float modelScale = 1;
            if (unit.Data.isSummonUnit && unit.Data.summonConfig.summon_show_type == 1)
            {
                renderer = UnitManager.Instance.GetGameObjectFromSummonDic(unit.Data.summonSkillIndex,
                    unit.Data.summonIndex);
            }

            //if (PveManager.Instance.isInRpg)
            {
                if (unit.Data.team == 0 && !unit.Data.isSummonUnit)
                {
                    renderer = DeckManager.Instance.GetHeroModel(unit.Data.positionId);
                }

                if (unit.Data.team == 2)
                {
                    renderer = DeckManager.Instance.GetMonsterModel(unit.Data.index);
                }
            }

            if (renderer == null)
            {
                if (unit is MortalUnit)
                {
                    var mortalUnit = unit as MortalUnit;
                    if (mortalUnit.SpecialNpc)
                    {
                        renderer = PveResourceManager.GetResource(PveResourceManager.EPveResType.GuideUseNpc, unit.Data.modelId);
                    }
                    else
                    {
                        renderer = PveResourceManager.GetResource(PveResourceManager.EPveResType.Npc, unit.Data.modelId);
                    }
                }
                else
                {
                    renderer = PveResourceManager.GetResource(PveResourceManager.EPveResType.Model, unit.Data.modelId);
                }

            }

            if (renderer == null)
            {
                renderer = new GameObject("renderer");
            }
            var lightElement = renderer.GetComponentInChildren<LightElement>();
            if (lightElement!=null)
            {
                if (PveMap.rpgLightController)
                {
                    PveMap.rpgLightController.AddLightElement(lightElement);
                }
            }

            unit.Data.rendererOriginScale = renderer.transform.localScale;
            //应fg要求boss模型放大20%
            if (unit.Data.isBoss)
            {
                renderer.transform.localScale = unit.Data.rendererOriginScale * PveGlobalVlues.BossScale;
            }
            //renderer.transform.localScale = //modelScale * new Vector3(PveUtils.globalRatio,PveUtils.globalRatio,PveUtils.globalRatio);
            renderer.transform.SetParent(unit.gameObject.transform);
            renderer.transform.localPosition = Vector3.zero;
            renderer.transform.localEulerAngles = Vector3.zero;

            
            unit.renderer = renderer;
            /*if (unit.Data.config.modelId == 998 || unit.Data.config.modelId == 1000 || unit.Data.config.modelId == 999)
            {
                renderer.transform.localScale = new Vector3(1.1f,1.1f,1.1f);
            }*/
            isAirDrone = false;
            timelineMono = renderer.GetComponent<ModelInTimeline>();
            if (timelineMono != null)
            {
                animator = timelineMono.realAnimator;
            }
            else
            {
                animator = renderer.GetComponentInChildren<Animator>();
            }
            if (animator != null)
            {
                animator.enabled = true;
                animator.speed = 1;
                animator.SetFloat("AttackSpeed",unit.Data.attackSpeedRatio);
                RigidEnd();
                
                //有时候会获取不到layer信息，所以延迟处理
                TimeManager.Instance.DelayCall(100, () =>
                {
                    if (animator == null)
                    {
                        return;
                    }
                    var attackFullLayerIndex = animator.GetLayerIndex("AttackFullLayer");
                    if (attackFullLayerIndex > 0)
                    {
                        animator.SetLayerWeight(attackFullLayerIndex, 0);
                    }

                    this.attackFullLayerIndex = attackFullLayerIndex;
                    var attackTopLayerIndex = animator.GetLayerIndex("AttackTopLayer");
                    if (attackTopLayerIndex > 0)
                    {
                        animator.SetLayerWeight(attackTopLayerIndex, 0);
                    }

                    this.attackTopLayerIndex = attackTopLayerIndex;
                    if (attackFullLayerIndex <= 0)
                    {
                        if (PveManager.Instance.isInRpg && unit.Data.modelId != PveGlobalVlues.HelicopterModelId &&
                            unit.Data.modelId != PveGlobalVlues.AirDroneModelId)
                        {
                            Debug.Log(animator.name + " 没有获取到layer信息");
                        }
                    }
                    lastAttackState = 0;
                });
               
                
                
                if (unit.Data.modelId == PveGlobalVlues.AirDroneModelId) //小飞机初始高度
                {
                    animRoot = animator.gameObject.transform;
                    rendererOffset = animRoot.localPosition;
                    isAirDrone = true;
                }
            }

            animators = renderer.GetComponentsInChildren<Animator>();
            targetBlendValue.Clear();
            currentBlendValue.Clear();
            deadDissolveStartTime = 0;
            targetBlendValue.Add("WalkV",0);
            targetBlendValue.Add("WalkH",0);
            targetBlendValue.Add("WalkSpeed",0);

            currentBlendValue.Add("WalkV",0);
            currentBlendValue.Add("WalkH",0);
            currentBlendValue.Add("WalkSpeed",0);

            meshRender = renderer.GetComponentsInChildren<SkinnedMeshRenderer>();
            shadowList.Clear();

            unit.Data.hitPoints = null;
            rotationAnchorPoint = null;
            var modelHitPoint = renderer.GetComponentInChildren<ModelHitPoint>();
            if (modelHitPoint != null)
            {
                unit.Data.hitPoints = modelHitPoint.hitPoints;
                unit.Data.gunPoints = modelHitPoint.gunPoints;
                unit.Data.hudPoint = modelHitPoint.hudPoint;
                unit.Data.hudHeight = modelHitPoint.hudHeight;
                unit.Data.bulletCasePoints = modelHitPoint.bulletCastPoints;
                unit.Data.skillEffectPoints = modelHitPoint.skillEffectPoints;
                unit.Data.buffEffectPoints = modelHitPoint.buffEffectPoints;
                unit.Data.flyTextPoint = modelHitPoint.flyTextPoint;
                unit.Data.flyTextCriticalPoint = modelHitPoint.flyTextCriticalPoint;
                rotationAnchorPoint = modelHitPoint.anchorPoint;
                if (rotationAnchorPoint != null)
                {
                    rotationAnchorPointOriginAngles = rotationAnchorPoint.transform.localEulerAngles;
                }
            }

            renderMats.Clear();
            shadowMat.Clear();
            hairs.Clear();
            //性能卡点
            if (meshRender.Length > 0)
            {
                for (int i = 0; i < meshRender.Length; i++)
                {
                    var obj = meshRender[i].gameObject;
                    var objLayer = obj .layer;
                    if (objLayer == PveUtils.agentHairLayer || objLayer == PveUtils.commanderHairLayer)
                    {
                        List<GameObject> hair;
                        if (!hairs.TryGetValue(objLayer,out hair))
                        {
                            hair = new List<GameObject>();
                            hairs[objLayer] = hair;
                        }
                        hair.Add(obj);
                    }
                    
                    var meshBlock = new MaterialPropertyBlock();
                    meshRender[i].GetPropertyBlock(meshBlock);
                    meshBlock.SetFloat("_Darkness",0);
                    renderMats.Add(new RendererMatData
                    {
                        renderer = meshRender[i],
                        propertyBlock = meshBlock,
                    });
                }
            }
            //else
            {
                var renderer = this.renderer.GetComponentsInChildren<MeshRenderer>();
                for (int i = 0; i < renderer.Length; i++)
                {
                    var meshBlock = new MaterialPropertyBlock();
                    renderer[i].GetPropertyBlock(meshBlock);
                    meshBlock.SetFloat("_Darkness",0);
                    renderMats.Add(new RendererMatData
                    {
                        propertyBlock = meshBlock,
                        renderer = renderer[i],
                    });
                    
                }
                SetFlashColor(Color.white);
            }

            SetMaskAmount(0);

            audioSource = renderer.GetComponent<AudioSource>();
            if (audioSource)
            {
                audioSource.volume = 0.2f;
            }

            ikCom = renderer.GetComponentInChildren<AimIK>();
            if (ikCom != null)
            {
                ikCom.solver.SetIKPositionWeight(0);
            }
            skillAnimator = null;
            effectAnimator = null;
            if (unit is BattleUnit && unit.Data.skillModelId != 0)
            {
                
                skillModel = PveResourceManager.GetResource(PveResourceManager.EPveResType.Model, unit.Data.skillModelId);
                if (skillModel != null)
                {
                    skillModel.transform.localScale = modelScale * new Vector3(PveUtils.globalRatio,PveUtils.globalRatio,PveUtils.globalRatio);
                    skillModel.transform.SetParent(unit.gameObject.transform);
                    skillModel.transform.localPosition = Vector3.zero;
                    skillModel.transform.localEulerAngles = Vector3.zero;
                    skillModel.SetActive(false);
                    var animators = skillModel.GetComponentsInChildren<Animator>();
                    {
                        for (int i = 0; i < animators.Length; i++)
                        {
                            if (animators[i].gameObject.name.Contains("ani"))
                            {
                                effectAnimator = animators[i];
                                effectAnimator.enabled = true;
                            }
                            else
                            {
                                skillAnimator = animators[i];
                                skillAnimator.enabled = true;
                            }
                        }
                    }
                }
            }

            if (unit.Data.config != null && unit.Data.config.animation_in)
            {
                SetVisible(false);
            }
            else
            {
                SetVisible(true);
            }
            isShowingIn = false;
            if (unit.Data.modelId == PveGlobalVlues.HelicopterModelId)
            {
                AudioManager.PlaySound("sfx_rpg_helicopter_idle",unit.gameObject);
            }
        }

        public void ValidateShadow(bool enable)
        {
            if (_ShowShadow!= enable)
            {
                foreach (var mat in shadowMat)
                {
                    mat.SetShaderPassEnabled("Always", enable);
                }
                _ShowShadow = enable;
            }
        }
        private void StartKnockBack()
        {
            unit.Data.SetTargetForward(unit.Data.damageForward);
            unit.Data.forward = unit.Data.targetForward;
            isShowKnockBack = true;
            startKnockBackTime = TimeManager.gameTime;
            forward = -unit.Data.forward;
            accelerate = -knockBackDistance * 2 / actionDuration / actionDuration;
            accelerateVertical = -knockBackHeight * 4 / actionDuration / actionDuration;
            knockBackSpeed = -accelerate * actionDuration;
            knockBackVerticalSpeed = -accelerateVertical * actionDuration / 2;
        }

        private void DoKnockBack()
        {
            if (renderer == null)
            {
                return;
            }
            if (TimeManager.gameTime - startKnockBackTime <= actionDuration)
            {
                renderer.transform.position += knockBackSpeed * TimeManager.GameDeltaTime * forward +
                                               knockBackVerticalSpeed * TimeManager.GameDeltaTime * Vector3.up;
                knockBackSpeed += accelerate * TimeManager.GameDeltaTime;
                knockBackVerticalSpeed += accelerateVertical * TimeManager.GameDeltaTime;
            }
            else
            {
                renderer.transform.position = new Vector3(renderer.transform.position.x,0,renderer.transform.position.z);
                isShowKnockBack = false;
            }
        }

        //抛飞相关
        private float knockBackSpeed = 0.3f;
        private float knockBackVerticalSpeed = 0.3f;
        private float accelerate = 1;
        private float accelerateVertical = 1;
        private float actionDuration = 0.4f;
        private float knockBackHeight = 1;
        private float knockBackDistance = 2f;
        private Vector3 forward;
        private bool isShowKnockBack;
        private float startKnockBackTime;


        private int deadCallId;
        private int deadDissolveCallId;
        private int deadTurnDarkCallId;
        private int deadDisappearCallId;
        private int deadHelicopterCallId;

        private float deadDissolveStartTime;
        private float deadTurnDarkStartTime;

        private bool isDropping;
        private float dropAccelerate = 30;
        private Vector3 dropSpeed;
        
        private void StartAirDroneDead()
        {
            var targetPosition = unit.Data.forward * 3 + unit.Data.position;
            if (unit.Data.lockTarget != null)
            {
                targetPosition = unit.Data.lockTarget.Data.position;
            }

            var offset = UnityEngine.Random.insideUnitCircle;
            targetPosition = targetPosition + new Vector3(offset.x, 0, offset.y);
            dropSpeed = (targetPosition - (unit.Data.position + rendererOffset)).normalized * 1;
            isDropping = true;
            Play("Drop");
        }

        private void CheckAirDroneDead()
        {
            if (!isDropping || animRoot == null)
            {
                return;
            }
            var position = animRoot.position;
            var accelerate = dropAccelerate * TimeManager.GameDeltaTime * dropSpeed.normalized;
            dropSpeed = dropSpeed + accelerate;
            var speedThisFrame = dropSpeed * TimeManager.GameDeltaTime;
         
            if (speedThisFrame.y != 0 && position.y + speedThisFrame.y <= 0)
            {
                speedThisFrame = Mathf.Abs(position.y) / Mathf.Abs(speedThisFrame.y) * speedThisFrame;
                isDropping = false;
                Play("Dead");

                unit.Data.position = position + speedThisFrame;
                unit.gameObject.transform.position = unit.Data.position;
                animRoot.localPosition = Vector3.zero;
                unit.Transmit(ETransmitType.Dead);
                unit.Data.isDying = false;
                return;
            }
            position += speedThisFrame;
            animRoot.position = position;
        }

        /// <summary>
        /// 临时写的获取死亡时长的方法
        /// </summary>
        /// <returns></returns>
        private float GetDeadActionTime()
        {
            if (animator != null)
            {
                var clips = animator.runtimeAnimatorController.animationClips;
                for (int i = 0; i < clips.Length; i++)
                {
                    var clip = clips[i];
                    var name = clip.name.ToLower();
                    if (name.Contains("dead") || name.Contains("death"))
                    {
                        return clip.length;
                    }
                }
                
            }
            return 0;
        }

        /// <summary>
        /// 临时写的获取入场时长的方法
        /// </summary>
        private float GetJoinBattleAnimationLength()
        {
            if (animator != null)
            {
                var clips = animator.runtimeAnimatorController.animationClips;
                for (int i = 0; i < clips.Length; i++)
                {
                    var clip = clips[i];
                    var name = clip.name.ToLower();
                    if (name.Contains("_in"))
                    {
                        return clip.length;
                    }
                }
            }
            return 0;
        }
        
        void IComponent.OnDead()
        {
            //ChangeBackPhantomMaterial();
            float deadTime = GetDeadActionTime();
            ClearShadow();
            Rigid();
            unit.Data.attackState = 0;
            UpdateAttackState(true);
            float roll = Random.Range(0, 1f);
            int extraTime = 0;

            unit.Data.isDying = true;
            if (isAirDrone)
            {
                StartAirDroneDead();
                return;
            }

            if (unit.Data.modelId == PveGlobalVlues.HelicopterModelId)
            {
                Play("Dead");
                deadHelicopterCallId = TimeManager.Instance.DelayCall((int)(57 / 30f * 1000), () =>
                {
                    AudioManager.StopSound("sfx_rpg_helicopter_idle",unit.gameObject);
                    AudioManager.PlaySound("sfx_rts_carblast",unit.gameObject);
                    /*PveEffectManager.Instance.PlayEffect((int)ESkillEffect.explosive,Data.position,Vector3.forward,5,2);
                    PveCameraManager.Instance.Shake(0.5f);*/
                });
            }
            else
            {
                if (roll <= PveGlobalVlues.deadEffect[0])
                {
                    extraTime = (int)(actionDuration * 1000) + 100;
                    StartKnockBack();
                }
                else if (roll <= PveGlobalVlues.deadEffect[0] + PveGlobalVlues.deadEffect[1])
                {
                    
                }
                else
                {
                    PveEffectManager.Instance.PlayEffect(25,unit.Data.position,Vector3.forward,5,1f);
                    //TimeManager.Instance.DelayCall(100, () =>
                    //{
                    if (renderer != null)
                    {
                        renderer.SetActive(false);
                    }

                    deadDisappearCallId = TimeManager.Instance.DelayCall(1000, () =>
                    {
                        unit.Data.isDying = false;
                    });

                    //});
                }
            }
            
            Play("Dead");
            deadTurnDarkCallId = TimeManager.Instance.DelayCall((int)(deadTime*1000) + extraTime, () =>
            {
                deadTurnDarkStartTime = TimeManager.gameTime;
            });
            deadDissolveCallId = TimeManager.Instance.DelayCall((int)((deadTime + 0.3f)*1000) + extraTime, () =>
            {
                deadDissolveStartTime = TimeManager.gameTime;
                for (int i = 0; i < renderMats.Count; i++)
                {
                    var data = renderMats[i];
                    if (data.renderer != null)
                    {
                        data.originMats = data.renderer.materials;
                        var newMats = new Material[data.originMats.Length];
                        for (int j = 0; j < newMats.Length; j++)
                        {
                            var mat = PveResourceManager.GetDeadDissolveMat();
                            newMats[j] = mat;
                        }

                        data.deadMats = newMats;
                        data.renderer.materials = newMats;
                        data.renderer.GetPropertyBlock(data.propertyBlock);
                    }
                }
            });

            deadCallId = TimeManager.Instance.DelayCall((int)((deadTime + 3)*1000) + extraTime, () =>
            {
                if (unit.Data.modelId == PveGlobalVlues.HelicopterModelId)
                {
                    unit.Data.isDying = false;
                    return;
                }
                for (int i = 0; i < renderMats.Count; i++)
                {
                    var data = renderMats[i];

                    if (data.renderer != null)
                    {
                        if (data.deadMats != null)
                        {
                            for (int j = 0; j < data.deadMats.Length; j++)
                            {
                                GameObject.DestroyImmediate(data.deadMats[j]);
                            }
                            data.deadMats = null;
                        }
                        data.renderer.materials = data.originMats;
                    }
                    for (int j = 0; j < data.originMats.Length; j++)
                    {
                        data.originMats[j].SetFloat("_Darkness",0);
                    }
                    
                }
                renderMats.Clear();
                if (renderer != null)
                {
                    renderer.transform.localScale = unit.Data.rendererOriginScale;
                    ResetHairsLayer();
                    UpdateAttackState(true);
                    PveResourceManager.RecoverResource(renderer,PveResourceManager.EPveResType.Model,unit.Data.modelId);
                }
                renderer = null;
                if (skillModel != null)
                {
                    PveResourceManager.RecoverResource(skillModel,PveResourceManager.EPveResType.Model,unit.Data.skillModelId);
                }

                needShowShadow = false;
                renderer = null;
                skillModel = null;
               
            });

        }

        public void SetMaskAmount(float amount)
        {
            /*for (int i = 0; i < flashMat.Count; i++)
            {
                flashMat[i].SetFloat(MaskAmount,amount);
            }*/
            SetFlashAmount(amount);
        }

        public void SetMaskColor(Vector4 color)
        {
            /*for (int i = 0; i < flashMat.Count; i++)
            {
                flashMat[i].SetVector(MaskColor,color);
            }*/
            SetFlashColor(color);
        }

        /*private void ChangeToPhantomMaterial()
        {
            for (int i = 0; i < renderMats.Count; i++)
            {
                var data = renderMats[i];
                data.usedPhantomMats = new List<Material>();
                for (int j = 0; j < data.indexs.Count; j++)
                {
                    var mat = PveResourceManager.GetPhantomMat();
                    data.phantomMats[data.indexs[j]] = mat;
                    data.usedPhantomMats.Add(mat);
                }

                if (data.meshRenderer != null)
                {
                    data.meshRenderer.materials = data.phantomMats;
                }
                else if (data.skinnedMeshRenderer != null)
                {
                    data.skinnedMeshRenderer.materials = data.phantomMats;
                }
            }
        }

        private void ChangeBackPhantomMaterial()
        {
            for (int i = 0; i < renderMats.Count; i++)
            {
                if (renderMats[i].usedPhantomMats == null)
                {
                    continue;
                }
                for (int j = 0; j < renderMats[i].usedPhantomMats.Count; j++)
                {
                    GameObject.DestroyImmediate(renderMats[i].usedPhantomMats[j]);
                }

                if (renderMats[i].meshRenderer != null)
                {
                    renderMats[i].meshRenderer.materials = renderMats[i].originMats;
                }
                else if (renderMats[i].skinnedMeshRenderer != null)
                {
                    renderMats[i].skinnedMeshRenderer.materials = renderMats[i].originMats;
                }
            }
        }*/

        private GameObject ball;

        public void UpdateGhostShadowVisible(bool visible)
        {
            needShowShadow = visible;
        }

        public void SetTrigger(string action)
        {
            if (animator && !unit.Data.isDead)
            {
                animator.SetTrigger(action);
            }
        }
        
        void ITransmit.OnTransmit(ETransmitType type, BaseTransmitArg arg)
        {
            if (type == ETransmitType.ShowGhostShadow)
            {
                needShowShadow = true;
                //ChangeToPhantomMaterial();
            }
            else if (type == ETransmitType.HideGhostShadow)
            {
                needShowShadow = false;
                //ChangeBackPhantomMaterial();
            }
            else if (type == ETransmitType.ShowOneGhostShadow)
            {
                //ChangeToPhantomMaterial();
                CreateShadow(1);
                //ChangeBackPhantomMaterial();
            }
            else if (type == ETransmitType.SwitchBall)
            {
                if (ball == null)
                {
                    ball = GameObject.CreatePrimitive(PrimitiveType.Sphere);
                    ball.transform.SetParent(unit.gameObject.transform);
                    ball.transform.localPosition = new Vector3(0,0.5f,0);
                }
                //ball.SetActive(!ball.activeSelf);
                renderer.SetActive(false);
            }
            else if (type == ETransmitType.OnSelectBySkill)
            {
                SetMaskColor(new Vector4(1,1,1,1));
                SetMaskAmount(0.3f);
            }
            else if (type == ETransmitType.OnUnSelectBySkill)
            {
                SetMaskAmount(0);
            }
            else if (type == ETransmitType.SkillForceStop)
            {
                Play("SkillForceStop");
            }
            else if (type == ETransmitType.BeHitByOthers)
            {
                /*lastFlashAmount = 0.5f;
                SetFlashAmount(lastFlashAmount);
                flashStartTime = TimeManager.logicTime;
                flashDuration = 0.1f;*/
                if (unit is ObstacleUnit)
                {
                    Shake(0.2f);
                }

                /*if (!unit.Data.isDead && animator != null && unit.Data.team == 2)//(unit.Data.id != 0 || !unit.Data.isMoveAttacking))
                {
                    animator.SetTrigger("Hit");
                }*/
            }
            else if (type == ETransmitType.PlayModelShake)
            {
                var shakeArg = arg as ModelShakeArg;
                Shake(shakeArg.model_shake_duration,shakeArg.model_shake_intensity,shakeArg.model_shake_rate);
            }
            else if (type == ETransmitType.PlayHitMotion)
            {
                if (!unit.Data.isDead && animator != null)
                {
                    animator.SetTrigger("Hit");
                }
            }
            else if (type == ETransmitType.PlayShootSound)
            {
                if (audioSource)
                {
                    audioSource.Stop();
                    audioSource.Play();
                }
            }
            else if (type == ETransmitType.Skill)
            {
                /*SetFlashColor(Color.white);
                lastFlashAmount = 1;
                SetFlashAmount(lastFlashAmount);
                flashStartTime = TimeManager.logicTime;
                flashDuration = 0.2f;
                flashFade = 0.1f;*/
            }
            else if (type == ETransmitType.AimTransform)
            {
                if (ikCom != null)
                {
                    ikCom.solver.target = unit.Data.aimTransform;
                    ikCom.solver.SetIKPositionWeight(1);
                    ikCom.enabled = true;
                }
                
            }
            else if (type == ETransmitType.CancelAim)
            {
                if (ikCom != null)
                {
                    ikCom.solver.target = null;
                    ikCom.solver.SetIKPositionWeight(0);
                    ikCom.enabled = false;
                }
            }
            else if (type == ETransmitType.Rigid)
            {
                Rigid();
            }
            else if (type == ETransmitType.RigidEnd)
            {
                RigidEnd();
            }
            else if (type == ETransmitType.ShowSkillModel)
            {
                if (skillModel != null)
                {
                    skillModel.SetActive(true);
                }
            }
            else if (type == ETransmitType.HideSkillModel)
            {
                if (skillModel != null)
                {
                    skillModel.SetActive(false);
                }
            }
            else if (type == ETransmitType.RPGStart)
            {
                if (animator != null)
                {
                    animator.applyRootMotion = false;
                }
            }
            else if (type == ETransmitType.ToRPG)
            {
                /*var shadowController = PveMap.rpgModelShadowController;
                if (shadowController != null)
                {
                    for (int i = 0; i < shadowMat.Count; i++)
                    {
                        var mat = shadowMat[i];
                        mat.SetColor("_ShadowColor",shadowController.color);
                        mat.SetVector("_ShadowOffset",new Vector4(shadowController.offsetX,shadowController.offsetY,shadowController.offsetZ,shadowController.offsetW));
                        mat.SetFloat("_ShadowHeight",shadowController.height);
                    }
                }*/
                
            }
            else if (type == ETransmitType.StageStart)
            {
                if (unit.Data.isManualMoving && animator != null)
                {
                    animator.applyRootMotion = true;
                }
            }
            else if (type == ETransmitType.AttackSpeedChange)
            {
                if (animator != null)
                {
                    animator.SetFloat("AttackSpeed",unit.Data.attackSpeedRatio);
                }
            }
            else if (type == ETransmitType.SkillFrameSpeedChange)
            {
                if (animator != null)
                {
                    animator.SetFloat("AttackSpeed",unit.Data.attackSpeedRatio * unit.Data.skillFrameSpeedChangeValue);
                }
            }
            else if (type == ETransmitType.Reborn)
            {
                unit.Data.isDead = false;
                unit.Data.CurrentHp = unit.Data.TotalHp;
                ((IClass)this).OnReset();
                ((IComponent)this).OnBirth();
                Play("Idle");
            }
            else if (type == ETransmitType.HideRenderer)
            {
                if (renderer != null)
                {
                    //renderer.SetActive(!renderer.activeSelf);
                    var objs = renderer.GetComponentsInChildren<SkinnedMeshRenderer>();
                    for (int i = 0; i < objs.Length; i++)
                    {
                        objs[i].enabled = false;
                    }
                    var objs2 = renderer.GetComponentsInChildren<MeshRenderer>();
                    for (int i = 0; i < objs2.Length; i++)
                    {
                        objs2[i].enabled = false;
                    }
                }
            }
            else if (type == ETransmitType.ShowRenderer)
            {
                if (renderer != null)
                {
                    //renderer.SetActive(!renderer.activeSelf);
                    var objs = renderer.GetComponentsInChildren<SkinnedMeshRenderer>();
                    for (int i = 0; i < objs.Length; i++)
                    {
                        objs[i].enabled = true;
                    }
                    var objs2 = renderer.GetComponentsInChildren<MeshRenderer>();
                    for (int i = 0; i < objs2.Length; i++)
                    {
                        objs2[i].enabled = true;
                    }
                }
            }
            else if (type == ETransmitType.LookAt)
            {
                LookAt((arg as LookAtArg).position);
            }
            else if (type == ETransmitType.BeforeAttack)
            {
                if (unit.Data.lockTarget != null)
                {
                    LookAt(unit.Data.lockTarget.Data.position);
                }
            }
            else if (type == ETransmitType.TimelineEnd)
            {
                showInTime = 0;
            }
            else if (type == ETransmitType.JoinBattle)
            {
                if (unit.Data.config.animation_in)
                {
                    //showInTime = GetJoinBattleAnimationLength();
                    SetVisible(true);
                    //Play("In");
                    unit.Data.isShowingSpawn = true;
                    showInStartTime = TimeManager.logicTime;
                    isShowingIn = true;
                    PveManager.Instance.OnTimelineStart(unit);
                    if (timelineMono)
                    {
                        var director = timelineMono.director;
                        //director.gameObject.SetActive(true);
                        showInTime = (float)director.duration;
                        var asset = director.playableAsset;
                        CinemachineTrack cameraTrack = null;
                        foreach (var bind in asset.outputs)
                        {
                            if (bind.outputTargetType == typeof(CinemachineBrain))
                            {
                                cameraTrack = bind.sourceObject as CinemachineTrack;
                            }
                            //Debug.LogError(bind.streamName + " " + bind.outputTargetType);
                        }

                        if (cameraTrack != null)
                        {
                            director.SetGenericBinding(cameraTrack, PveCameraManager.Instance.rpgBrain);
                            foreach (var clip in cameraTrack.GetClips())
                            {
                                if (clip.asset is CinemachineShot shot)
                                {
                                    var camera = PveCameraManager.Instance.GetRpgCameraByName(clip.displayName);
                                    if (camera != null)
                                    {
                                        shot.VirtualCamera = new ExposedReference<CinemachineVirtualCameraBase>
                                        {
                                            defaultValue = camera
                                        };
                                        if (clip.displayName == "BattleBoss")
                                        {
                                            bossFixedCamera = camera;
                                        }
                                        else if (clip.displayName == "BossCome")
                                        {
                                            bossComeCamera = camera;
                                        }
                                    }
                                   
                                }
                                /*if (clip.displayName == "CinemachineShot")
                                {
                                    var info = clip.asset as CinemachineShot;
                                    clip.
                                }*/
                                
                            }
                        }

                        if (bossFixedCamera)
                        {
                            bossFixedCamera.enabled = true;
                            bossFixedCamera.Follow = PveCameraManager.Instance.cameraFocusToken.transform;
                            bossFixedCamera.LookAt = PveCameraManager.Instance.cameraFocusToken.transform;
                        }

                        if (bossComeCamera)
                        {
                            bossComeCamera.enabled = true;
                            bossComeCamera.Follow = renderer.transform;
                            bossComeCamera.LookAt = renderer.transform;
                        }
                        director.Play();
                    }
                }
            }
            else if (type == ETransmitType.StartRootMotion)
            {
                if (animator)
                {
                    animator.applyRootMotion = true;
                }
            }
            else if (type == ETransmitType.EndRootMotion)
            {
                if (animator)
                {
                    animator.applyRootMotion = false;
                }
            }
        }

        private void ResetTimeline()
        {
            if (bossComeCamera)
            {
                bossComeCamera.enabled = false;
                bossComeCamera.Follow = null;
                bossComeCamera.LookAt = null;
                bossComeCamera = null;
            }

            if (bossFixedCamera)
            {
                bossFixedCamera.enabled = false;
                PveCameraManager.Instance.ResetBattleFixFakeCamera();
                bossFixedCamera.Follow = null;
                bossFixedCamera.LookAt = null;
                bossFixedCamera = null;
            }
        }

        private void LookAt(Vector3 position)
        {
            if (rotationAnchorPoint != null)
            {
                var aimYOffset = 0.5f;
                var groundPosition = rotationAnchorPoint.transform.position;
                groundPosition.y = 0;
                var a = 1;//枪管距离锚点的高度
                var d = Vector3.Distance(groundPosition,position);
                var h = rotationAnchorPoint.transform.position.y - aimYOffset;
                var a2 = a * a;
                var d2 = d * d;
                var h2 = h * h;
                var h4 = h2 * h2;

                var distanceOffset = (-2 * a2 * d - 2 * a * Mathf.Sqrt(d2 - (a2 * d2 + a2 * h2 - d2 * h2 - h4))) / (2 * a2 - 2 * h2);

                var distanceOffsetExtraByAimYOffset =
                    (-distanceOffset + Mathf.Sqrt(distanceOffset * distanceOffset + 4 * aimYOffset * (h + aimYOffset)))/2;

                distanceOffset += distanceOffsetExtraByAimYOffset;

                var maxAngle = 15;
                var minDistanceOffset = rotationAnchorPoint.transform.position.y / Mathf.Tan(maxAngle * Mathf.Deg2Rad);

                distanceOffset = Mathf.Max(distanceOffset, minDistanceOffset - d);
                
                var distanceOffsetDirection = (position - groundPosition).normalized;
                position = position + distanceOffsetDirection * distanceOffset;
                lookAtTargetForward = (position - rotationAnchorPoint.position).normalized;
                rotationAnchorPoint.DOKill();
                rotationAnchorPoint.DOLookAt(position, 1);
            }
        }

        private void Rigid()
        {
            if (animator == null)
            {
                return;
            }
            int layer = animator.GetLayerIndex("HitLayer");
            if (layer >= 0)
            {
                animator.SetLayerWeight(layer,0f);
            }
        }

        private void RigidEnd()
        {
            if (animator == null)
            {
                return;
            }
            int layer = animator.GetLayerIndex("HitLayer");
            if (layer >= 0)
            {
                animator.SetLayerWeight(layer,1f);
            }
        }

        private void Shake(float time,float intensity = 0.1f,int rate = 100)
        {
            lastShakeTime = 0;
            shakeInterval = 1f / rate;
            shakeStartTime = TimeManager.gameTime;
            shakeTime = time;
            this.shakeIntensity = intensity;
            shakeOffset = Vector3.zero;
        }

        private void CheckShake()
        {
            if (renderer == null)
            {
                return;
            }
            if (shakeStartTime != 0)
            {
                if (TimeManager.gameTime - shakeStartTime > shakeTime)
                {
                    shakeOffset = Vector3.zero;
                    shakeStartTime = 0;
                }
                else if (TimeManager.gameTime - lastShakeTime >= shakeInterval)
                {
                    Vector3 position = Random.insideUnitSphere * shakeIntensity;
                    //position.y = Mathf.Abs(position.y);
                    position.y = 0;
                    shakeOffset = position;
                    lastShakeTime = TimeManager.gameTime;
                }
            }
        }

        public void SetIsStun(bool isStun)
        {
            if (animator == null || unit.Data.isDead)
            {
                return;
            }

            if (isStun)
            {
                animator.ResetTrigger("StunEnd");
                animator.SetTrigger("Stun");
            }
            else
            {
                animator.ResetTrigger("Stun");
                animator.SetTrigger("StunEnd");
            }
        }

        public void ChangeAttackState(int state)
        {
            unit.Data.attackState = state;
            UpdateAttackState(true);
        }

        public void Play(string action)
        {
            if (unit.Data.isDead && action != "Dead" && !isAirDrone)
            {
                return;
            }
            if (animator == null)
            {
                return;
            }

            if (string.IsNullOrEmpty(action))
            {
                return;
            }
            
            if (m_action != action)
            {
                BattleLog.UnitLog(unit,"Play " + action);
            }

            if (!string.IsNullOrEmpty(m_action))
            {
                animator.ResetTrigger(m_action);
            }
            animator.SetTrigger(action);
            /*if (action == "MoveAttack" || action == "Attack")
            {

            }*/
            if (skillModel != null && skillModel.activeInHierarchy)
            {
                if (skillAnimator != null)
                {
                    if (!string.IsNullOrEmpty(m_action))
                    {
                        skillAnimator.ResetTrigger(m_action);
                    }
                    skillAnimator.SetTrigger(action);
                }
            }
            m_action = action;

            /*if (action.Contains("MoveAttack"))
            {
                if (moveAttackFullLayerIndex >= 0)
                {
                    animator.SetLayerWeight(moveAttackFullLayerIndex,1);
                }
            }
            else
            {
                if (moveAttackFullLayerIndex >= 0)
                {
                    animator.SetLayerWeight(moveAttackFullLayerIndex,0);
                }
            }*/
        }

        private string m_effectAction;

        public void PLaySkill(string action)
        {
            if (effectAnimator != null)
            {
                if (!string.IsNullOrEmpty(m_effectAction))
                {
                    effectAnimator.ResetTrigger(m_effectAction);
                }
                effectAnimator.SetTrigger(action);
                //unit.Log("Skill "+action);
                m_effectAction = action;
            }
        }

        public void UpdateSkillModelVisible(bool isVisible)
        {
            if (skillModel != null)
            {
                skillModel.SetActive(isVisible);
            }
        }
        
        public void SetAnimSpeed(float speed)
        {
            return;
            if (animator == null)
            {
                return;
            }

            if (speed >= 0)
            {
                animator.speed = speed;
                animator.SetFloat("Speed",speed);
            }
            else
            {
                animator.speed = 1;
                animator.SetFloat("Speed",speed);
            }
        }

        private Dictionary<string, float> targetBlendValue = new Dictionary<string, float>();
        private Dictionary<string, float> currentBlendValue = new Dictionary<string, float>();

        private int lastMoveState;

        public void SetDirection()
        {
            if (animator == null)
            {
                return;
            }

            if (unit.Data.moveState == 2 || unit.Data.moveState == 3)
            {
                if (unit.Data.isManualMoving)
                {
                    unit.Data.SetTargetForward(unit.Data.manualForward);
                }
                targetBlendValue["WalkSpeed"] = 2;
                /*if (unit.Data.config.runSpeedRatio > 0)
                {
                    animator.SetFloat("MoveSpeedRatio",unit.Data.config.runSpeedRatio);
                }*/
                unit.Data.configMoveSpeed = unit.Data.runSpeed;
            }
            else if (unit.Data.moveState == 1 || unit.Data.moveState == 4 || unit.Data.moveState == 5)
            {
                var angle = PveUtils.GetAngle(unit.Data.forward, Vector3.forward);
                var forwardDiff = Quaternion.AngleAxis(angle,Vector3.up) * unit.Data.manualForward.normalized;
                var xAbs = Mathf.Abs(forwardDiff.x);
                var zAbs = Mathf.Abs(forwardDiff.z);
                var ratio = 0f;
                if (xAbs != 0 || zAbs != 0)
                {
                    ratio = xAbs > zAbs ? 1 / xAbs : 1 / zAbs;
                }

                //if (unit.Data.isManualMoving)
                {
                    targetBlendValue["WalkV"] = forwardDiff.z * ratio;
                    targetBlendValue["WalkH"] = forwardDiff.x * ratio;
                }
                /*else
                {
                    targetBlendValue["WalkV"] = -1;
                    targetBlendValue["WalkH"] = 0;
                }*/
                if (unit.Data.moveState == 4 || unit.Data.moveState == 5)
                {
                    targetBlendValue["WalkSpeed"] = 2;
                }
                else
                {
                    targetBlendValue["WalkSpeed"] = 1;
                }
                if (unit.Data.walkSpeedRatio > 0)
                {
                    animator.SetFloat("MoveSpeedRatio",unit.Data.walkSpeedRatio);
                }
                unit.Data.configMoveSpeed = unit.Data.walkSpeed;
            }
            else
            {
                targetBlendValue["WalkV"] = 0;
                targetBlendValue["WalkH"] = 0;
                //if (unit.Data.IsInAttack() || unit.Data.isReloading || unit.Data.followTarget != null || unit.Data.IsInSkill())
                {
                    targetBlendValue["WalkSpeed"] = 0;
                }
                //targetBlendValue["WalkSpeed"] = 0;
            }

            //if (lastMoveState != unit.Data.moveState || unit.Data.IsInSkill())
            {
                var speed = targetBlendValue["WalkSpeed"];
                if (lastMoveState == 0 || unit.Data.IsInSkill() || !PveManager.Instance.IsStageActive)
                {
                    currentBlendValue["WalkSpeed"] = speed;
                    if (animator != null)
                    {
                        animator.SetFloat("WalkSpeed", speed);
                    }
                }
                //unit.Log("moveState " + unit.Data.moveState);
                //unit.Log("WalkSpeed " + speed);
            }
            lastMoveState = unit.Data.moveState;
        }

        private void CheckBlend()
        {
            if (animator == null)
            {
                return;
            }

            foreach (var item in targetBlendValue)
            {
                var targetBlendValue = item.Value;
                var currentBlendValue = this.currentBlendValue[item.Key];
                if (currentBlendValue != targetBlendValue)
                {

                    var speed = (targetBlendValue > currentBlendValue ? 1 : -1) * TimeManager.GameDeltaTime * 20;
                    var value = currentBlendValue + speed;
                    if ((value - targetBlendValue) * speed > 0)
                    {
                        currentBlendValue = targetBlendValue;
                    }
                    else
                    {
                        currentBlendValue += speed;
                    }
                    this.currentBlendValue[item.Key] = currentBlendValue;
                    animator.SetFloat(item.Key, currentBlendValue);
                }
            }
        }

        private void CheckDeadDissolve()
        {
            if (deadDissolveStartTime != 0)
            {
                float value = (TimeManager.gameTime - deadDissolveStartTime) / 1f;
                if (value <= 1)
                {
                    for (int i = 0; i < renderMats.Count; i++)
                    {
                        var pb = renderMats[i].propertyBlock;
                        if (pb != null)
                        {
                            pb.SetFloat("_Dissolve",value);
                            if (renderMats[i].renderer != null)
                            {
                                renderMats[i].renderer.SetPropertyBlock(pb);
                            }
                        }
                    }
                }
                else
                {
                    deadDissolveStartTime = 0;
                }
            }

            if (deadTurnDarkStartTime != 0)
            {
                float value = (TimeManager.gameTime - deadTurnDarkStartTime) / 0.3f;
                if (value <= 1)
                {
                    for (int i = 0; i < renderMats.Count; i++)
                    {
                        var pb = renderMats[i].propertyBlock;
                        if (pb != null)
                        {
                            pb.SetFloat("_Darkness",value);
                            if (renderMats[i].renderer != null)
                            {
                                renderMats[i].renderer.SetPropertyBlock(pb);
                            }
                        }
                    }
                }
                else
                {
                    unit.Data.isDying = false;
                    deadTurnDarkStartTime = 0;
                }
            }

        }

        private Dictionary<string,int> actionPriority = new Dictionary<string, int>
        {
            ["Dead"] = 5,
            ["Cheer"] = 3,
            ["Attack"] = 3,
            ["Run"] = 2,
            ["Walk2"] = 2,
            ["Walk"] = 2,
            ["Idle"] = 1,
            [string.Empty] = 0,
        };

        public void BeforeUpdate()
        {
            //m_currentFrameAction = string.Empty;
        }

        public bool IsNeedShowFlag = false;
        public float ShowStartTime;
        public void LateUpdate()
        {
            if (unit.Data.isDead)
            {
                if (animator != null)
                {
                    animator.speed = 1;
                }
            }
            UpdateForward();


            if (IsNeedShowFlag)
            {
                float time = TimeManager.logicTime - ShowStartTime;
                if (time < 1.3f)
                {
                    SetAlpha(time / 1);
                }
                else
                {
                    if (clothMobileUEMat)
                    {
                        clothMobileUEMat.SetInt("_BlendSrcFactor",(int)BlendMode.One);
                        clothMobileUEMat.SetInt("_BlendDstFactor",(int)BlendMode.Zero);
                    }
                    SetAlpha(1);
                    IsNeedShowFlag = false;
                }
            }

            return;
            if (m_currentFrameAction != string.Empty)
            {
                if (animator == null)
                {
                    return;
                }

                if (unit.Data.isDead && m_currentFrameAction != "Dead")
                {
                    return;
                }
                if (!(m_action == m_currentFrameAction && (m_currentFrameAction.Contains("Idle") || m_currentFrameAction.Contains("Run"))))
                {

                    animator.ResetTrigger(m_action);
                    animator.SetTrigger(m_currentFrameAction);
                    m_action = m_currentFrameAction;
                }
            }
            m_currentFrameAction = string.Empty;
        }

        private void SetAlpha(float alpha)
        {
            //todo 不支持alpha
            /*if (clothMobileUEMat != null)
            {
                clothMobileUEMat.SetColor("_BaseColor", new Color(baseColor.r, baseColor.g, baseColor.b, alpha));
            }
            else
            {
                Debug.LogError(renderer.gameObject.name+"clothMobileUEMat材质为空");
            }*/
        }

        private Color baseColor;
        public void Unscaled()
        {
            /*if (animator != null)
            {
                animator.updateMode = AnimatorUpdateMode.UnscaledTime;
            }*/
            var animators = unit.gameObject.GetComponentsInChildren<Animator>();
            for (int i = 0; i < animators.Length; i++)
            {
                animators[i].updateMode = AnimatorUpdateMode.UnscaledTime;
            }
        }

        public void Scaled()
        {
            /*if (animator != null)
            {
                animator.updateMode = AnimatorUpdateMode.Normal;
            }*/
            var animators = unit.gameObject.GetComponentsInChildren<Animator>();
            for (int i = 0; i < animators.Length; i++)
            {
                animators[i].updateMode = AnimatorUpdateMode.Normal;
            }
        }

        private AnimatorUpdateMode animatorUpdateMode;

        public void Pause()
        {
            for (int i = 0; i < animators.Length; i++)
            {
                var animator = animators[i];
                if (animator == null)
                {
                    continue;
                }
                if (animator == this.animator)
                {
                    animatorUpdateMode = animator.updateMode;
                }
                animator.updateMode = AnimatorUpdateMode.Normal;
                animator.speed = 0;
            }
            
            
            if (skillAnimator != null)
            {
                skillAnimator.speed = 0;
            }

            if (effectAnimator != null)
            {
                effectAnimator.speed = 0;
            }

            if (timelineMono != null)
            {
                timelineMono.director.Pause();
            }
        }

        public void Resume()
        {
            for (int i = 0; i < animators.Length; i++)
            {
                var animator = animators[i];
                if (animator == null)
                {
                    continue;
                }

                if (animator == this.animator)
                {
                    animator.updateMode = animatorUpdateMode;
                }
                animator.speed = 1;
            }
            
            
            if (skillAnimator != null)
            {
                skillAnimator.speed = 1;
            }

            if (effectAnimator != null)
            {
                effectAnimator.speed = 1;
            }
            
            if (timelineMono != null)
            {
                timelineMono.director.Resume();
            }
        }

        public void SetAnimatorBool(string name, bool value)
        {
            //unit.Log("Squat " + value);
            //m_action = string.Empty;
            if (animator != null)
            {
                animator.SetBool(name,value);
            }
        }

        public void ChangeToDeadModel()
        {
            if (renderer != null)
            {
                ResetHairsLayer();
                ResetTimeline();
                UpdateAttackState(true);
                if (animRoot != null)
                {
                    animRoot.transform.localPosition = rendererOffset;
                }
                animRoot = null;
                PveResourceManager.RecoverResource(renderer,PveResourceManager.EPveResType.Model,unit.Data.modelId);
            }
            renderer = PveResourceManager.GetResource(PveResourceManager.EPveResType.Model, unit.Data.deadModelId);
            renderer.transform.SetParent(unit.gameObject.transform);
            renderer.transform.localPosition = Vector3.zero;
            renderer.transform.localEulerAngles = Vector3.zero;
        }

        public void SetVisible(bool visible)
        {
            if (renderer != null)
            {
                renderer.gameObject.SetActive(visible);
            }
        }
    }
}
